package test;

import helpers.d;
import soenudp.Command;
import soenudp.UDPHelper;
import soenudp.UDPMessage;
import soenudp.UDPException;

/**
 * @author Davis - 5715822
 */
@SuppressWarnings("unused")
public class testUDP{
  
  private static String nodeID;

  // START Leader Test -----------------------------------------------------------
  private static void doLeaderStuff() {
    try {   
      UDPHelper udpHelper = new UDPHelper();

      // Join-Create Group at address 235.255.0.1 Port: 4495.
      udpHelper.joinGroup("235.255.0.1", 9200, true, nodeID); 
      d.sleep(3*1000); // Delay to start the group's replicas . 
      
      /*UDPMessage msg_1 = new UDPMessage("MTL777", Command.CHECK,  15,  1, null);
      UDPMessage msg_2 = new UDPMessage("MTL100", Command.RESERVE,20, 2, null);
      UDPMessage msg_3 = new UDPMessage("MTL100", Command.CANCEL, 12, 3, null);
      UDPMessage msg_4 = new UDPMessage(null    , Command.BPING,  0, 0, "Hi");
      UDPMessage msg_5 = new UDPMessage();
      */
      
     //UDPMessage msg_5 = new UDPMessage(); //msg_5.command = Command.UPDATED; //Short commands...
     //udpHelper.sendToNode(sentToIP, sentToPort, message)
      int i=0;
      for (int k=0; k <100; k++){
      //  udpHelper.sendToGroup(msg_1); 
      }
      /*
      for (i=0; i < 20; i++){
        udpHelper.sendToGroup(msg_1); 
        d.out("Sent " + msg_1.command); 
        d.sleep(100); // Wait test
        udpHelper.sendToGroup(msg_2);
        d.out("Sent " + msg_2.command);
        d.sleep(100); // Wait test
        udpHelper.sendToGroup(msg_3); 
        d.sleep(100); // Wait test
        udpHelper.sendToGroup(msg_4);   
        d.out("Send " + msg_4.command);
        d.sleep(100); // Wait test
        udpHelper.sendToGroup(msg_5);   
        d.out("Send " + msg_5.command);
      }
      */
      udpHelper.leaveGroup();   // isLeader = true closes Leader resources.
      //udpHelper.leaveGroup(true); // A second time to check the UDPException.
      
    } catch (UDPException e) {
      System.err.println("Caught UDPException");
      /* Leave group if still connected. (I doub't you are). Next time the GMS
       * broadcast the BPING, he will notice that you're missing and 'wake up' 
       * the passive node. She will be needed for re-election. 
       *
       * Who has a valid snapshot? GMS might inquire on the last trasaction id 
       * that was commited to the front-end. I do hope someone still have the 
       * cut...
       */
      e.printStackTrace();
    }
  }
  // END Leader Test -------------------------------------------------------------


  // START Replica Test ----------------------------------------------------------
  private static void doReplicaStuff() {
    final UDPHelper udpHelper = new UDPHelper();
    Runnable testRun = new Runnable() { 
      public void run() {     
        try {          
          // Use isLeader = false to receive messages from leader.
          udpHelper.joinGroup("235.255.0.1", 9200, false, nodeID);
         
          UDPMessage message; // Will wait in while() if no new messages
          int i=0;
          while ( (message = udpHelper.getMsgFromGroup()) != null ){
            i++;
            handleYourNew(message); 
            System.out.println("---->" + i);
          }
          
          udpHelper.leaveGroup(); // It's ending run so leave group.          
        } catch (UDPException e) {
            /* Next time the GMS update his view, this replica won't reply to BPING. 
             * GMS, send a'wake up' message to the waiting passive so the group can be
             * 3 again...  
             */
            System.err.println("UDPException");
            e.printStackTrace();
        }  
      }
    };
    Thread receiverThread = new Thread(testRun);
    receiverThread.start();
    //doSleep(60*1000); // Give a minute run to the replica...
    //receiverThread.interrupt(); // then we interrupt to end.
  }
  
  /* This could be a good place to handle messages */
  private static void handleYourNew(final UDPMessage message) {
    System.out.println("Received\n" + message);
  }  
  
  /* Could be used to switch from 'Replica' to 'Leader' state. */
  public static void setNodeID(String _nodeID) {
    nodeID = _nodeID;
  }
  // END Replica TEST ------------------------------------------------------------
  
  private static boolean isUsageBad(String[] args) {
    // Possible arguments are Front-End, Leader, Replica, Passive.
    // NodeID must be a non-null String.
    if (args.length > 1) return false;
    System.out.println("Usage example: java test.TestUDP Replica MTL002");
    return true;
  }
  
  public static void main(String[] args) {    
    boolean terminate = isUsageBad(args);
    if (terminate) return; /* End main */
    /* else try a run */
    nodeID = args[1];
    
    if (args[0].equals("Front-End"))     doFEStuff();
    else if (args[0].equals("Leader"))   doLeaderStuff();
    else if (args[0].equals("Replica"))  doReplicaStuff();
    else if (args[0].equals("Passive"))  doPassiveStuff();
    else /* Or put your glasses */  System.err.println("Unimplemented State");
  }
  
  private static void doFEStuff()               { /* Unimplemented */ }
  private static void doPassiveStuff()          { /* Unimplemented */ }
}
